/*
 * C implementation of Weazel.Math routines
 */

#ifndef _NativeMath_h_
#define _NativeMath_h_ 1

#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) < (b)) ? (b) : (a))

#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif

#define TRUE 1
#define FALSE 0

#include <stdlib.h>

typedef unsigned char BYTE;
typedef unsigned int BOOL; /* unsigned char gives do...while bug in Visual Studio 2005 December CPT build */
typedef unsigned int UINT;
typedef unsigned long long int ULONG;
typedef signed   long long int LONG;

/* an array of UINT's with associated length */
typedef struct uintarray
{
  int  length;
  UINT* values;
} uintarray;

typedef struct ninteger
{
  BOOL issigned;
  size_t  width;
  uintarray* content;
} ninteger;

/* used internally */
typedef enum strtype{
	strtype_invalid,
	strtype_bin,
	strtype_oct,
	strtype_dec,
	strtype_hex
} strtype;



/* internal helper routines */
uintarray*	alloc_uintarr(const int length);
void				free_uintarr(uintarray* arr);
void				free_ninteger(const ninteger* value);
void        resize(ninteger* value, const size_t newsize);

strtype getstrtype(const char* str);
void negateinternal(const uintarray* a, uintarray* r);
BOOL iszeroarr(const uintarray* content);

void addinternal2(const uintarray* a, const UINT b, uintarray* result);
void mulinternal2(const uintarray* a, const UINT b, const uintarray* r);
void divinternal2(uintarray** r, UINT* remainder, const uintarray* a, UINT b);

/* constructors */
EXPORT ninteger* newint(const int width, const BOOL issigned);
EXPORT ninteger* newintfromstr(const char* value);

/* assignment */
EXPORT void assignint (const int   value, const ninteger* target);
EXPORT void assignuint(const UINT  value, const ninteger* target);
EXPORT void assignlong(const LONG  value, const ninteger* target);
EXPORT void assignstr (const char* value, const ninteger* target);
EXPORT void assignbinstr (const char* value, const ninteger* target);
EXPORT void assigndecstr (const char* value, const ninteger* target);
EXPORT void assignhexstr (const char* value, const ninteger* target);

/* miscellaneous */
EXPORT void signextend(const ninteger* value, const UINT position);
EXPORT BOOL isnegative(const ninteger* value);
EXPORT void valuecopy(const ninteger* value, const ninteger* result);
EXPORT void negate(const ninteger* value, const ninteger* result);

/* bit manipulation */
EXPORT void getrange(const ninteger* value, const int index1, const int index2, ninteger* result);
EXPORT BOOL getbit(const ninteger* value, const UINT position);
EXPORT void setbit(const ninteger* value, const UINT position); 
EXPORT void clrbit(const ninteger* value, const UINT position); 

/* mathematical operations */
EXPORT void add(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void sub(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void mul(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void mod(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void divide(const ninteger* a, const ninteger* b, ninteger** result);

/* logical operations */
EXPORT void _and(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void ior(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void _xor(const ninteger* a, const ninteger* b, const ninteger* result);
EXPORT void shl(const ninteger* a, const int value, const ninteger* result);
EXPORT void shr(const ninteger* a, const int value, const ninteger* result);
EXPORT void _not(const ninteger* a, const ninteger* result); 

/* conversions */
EXPORT void tobinstr(const ninteger* value, const char* buffer, const size_t capacity); 
EXPORT void todecstr(const ninteger* value, const char* buffer, const size_t capacity); 
EXPORT void tohexstr(const ninteger* value, const char* buffer, const size_t capacity); 

EXPORT int  toint(const ninteger* value); 
EXPORT UINT touint(const ninteger* value); 

/* comparisons */
EXPORT BOOL iszero(const ninteger* value);
EXPORT BOOL areequal(const ninteger* a, const ninteger* b);
EXPORT BOOL isgreater(const ninteger* a, const ninteger* b);


#ifndef _Constants_h_
  extern const unsigned int bitmasks[];
  extern const unsigned int bitmasks2[];
  extern const BYTE BASE_TYPE_BITS;
  extern const UINT BASE_MAX_VALUE;
#else 
  const unsigned int bitmasks[];
  const unsigned int bitmasks2[];
  const BYTE BASE_TYPE_BITS;
  const UINT BASE_MAX_VALUE;
#endif /* _Constants_h_ */

#endif /* _NativeMath_h_ */

